package com.htjc.integral.common.aspect;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.htjc.integral.common.annotation.InvokeLog;
import com.htjc.integral.common.util.StringUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * 方法调用前后、异常及结果返回时记录日志
 * @author hlc
 */
@Slf4j(topic = "jfLog")
@Aspect
@Component
public class InvokeLogAdvice implements Ordered{

	private static long executeTime;

	private static boolean containsKey;

	private static String returnMsg;

	@Pointcut("execution(public * com.htjc..*.*(..))&&@annotation(invokeLog)")
	public void pointCut(InvokeLog invokeLog) {
	}

	//后置通知  打印返回报文 调用结束
	@AfterReturning(pointcut = "pointCut(invokeLog)", returning = "returnValue")
	public void doAfterReturning(JoinPoint joinPoint, InvokeLog invokeLog, Object returnValue) {
		log.info(invokeLog.retMsg(),invokeLog.value(),returnValue.toString());
		log.info(invokeLog.end(),invokeLog.value(),executeTime);
	}

	//例外通知 异常 调用结束
	@AfterThrowing(pointcut = "pointCut(invokeLog)", throwing = "e")
	public void doAfterThrowing(JoinPoint joinPoint, Exception e, InvokeLog invokeLog) throws Exception {
		log.error(invokeLog.ex(),invokeLog.value(),e.getMessage());
		log.info(invokeLog.end(),invokeLog.value(),executeTime);
	}

	/**
	 * 打印参数
	 *
	 * @param joinPoint
	 * @param invokeLog
	 * @param LOGGER
	 */
	private void printArgs(JoinPoint joinPoint, InvokeLog invokeLog) {
		Object[] args = joinPoint.getArgs();
		int argLength = args.length;
		if (argLength == 0) return;
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < argLength; i++) {
			Object arg = args[i];
			if (arg instanceof Number || arg instanceof CharSequence || arg instanceof Character) {
				buffer.append(arg);
			} else {
				buffer.append(JSON.toJSONString(arg));
			}
			if (i < argLength - 1) {
				buffer.append(",");
			}
		}
		log.info(invokeLog.args(),invokeLog.value(),buffer.toString());
		JSONObject argJson=(JSONObject) JSONObject.parse(args[0].toString());
		String[] params=invokeLog.params();
		containsKey=true;
		//引用传递
		for (String param : params) {
//			if (argJson.get(param) instanceof JSONObject) {
				if(!argJson.containsKey(param)||argJson.get(param)==null||StringUtil.isNull(argJson.get(param).toString())){
					containsKey=false;
					returnMsg=param+"为空";
					log.error(invokeLog.paramNull(),invokeLog.value(),param);
					return;
				}
//			}
		}
	}
	// 打印开始、请求报文、执行耗时
	@Around("pointCut(invokeLog)")
	public Object logInvokeTime(ProceedingJoinPoint joinPoint,InvokeLog invokeLog) throws Throwable {
		long start = System.currentTimeMillis();//开始时间
		log.info(invokeLog.start(),invokeLog.value());
		printArgs(joinPoint,invokeLog);
		try {
			//如果没有参数为空，执行方法
			if(containsKey){
				return joinPoint.proceed();
			}
			//有参数为空，返回报错
			JSONObject resultJson=new JSONObject();
			resultJson.put("rcode", "-1");
			resultJson.put("message", returnMsg);
			return resultJson.toString();
		} finally {
			long end = System.currentTimeMillis();//结束时间
			executeTime = end - start;
		}
	}
	
	@Override  
    public int getOrder() {  
        return 1001;  
    }
	//前置通知 打印调用开始并打印请求报文
	//    @Before("pointCut(invokeLog)")
	//    public void doBefore(JoinPoint joinPoint, InvokeLog invokeLog) {
	//        log.info(invokeLog.start(),invokeLog.value());
	//        printArgs(joinPoint,invokeLog);
	//    }

	//最终通知  打印调用结束
	//  @After("pointCut(invokeLog)")
	//  public void doAfter(JoinPoint joinPoint, InvokeLog invokeLog) {
	//  	log.info(invokeLog.end(),invokeLog.value());
	//  }
}
